using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SDAT;
using System.IO;
using System.Runtime.InteropServices;

namespace MKDS_Course_Editor
{
    public partial class sdat_ : Form
    {
        string name;
        byte[] file;
        sSDAT sd = new sSDAT();
        Players.MusicPlayer m;
        public sdat_(byte[] file, string name, Players.MusicPlayer m)
        {
            InitializeComponent();
            this.name = name;
            this.file = file;
            imageList1.Images.Add(Properties.Resources.folder);
            imageList1.Images.Add(Properties.Resources.snd);
            imageList1.Images.Add(Properties.Resources.swar);
            imageList1.Images.Add(Properties.Resources.music_beam_16);
            imageList1.Images.Add(Properties.Resources.guitar);
            imageList1.Images.Add(Properties.Resources.music_beam_16_archive);
            imageList1.Images.Add(Properties.Resources.question_white);
            imageList1.Images.Add(Properties.Resources.speaker);
            this.m = m;
        }
        public TreeNode CarpetaToNodo(Folder carpeta)
        {
            TreeNode currNode = new TreeNode();

            currNode = new TreeNode(carpeta.name, 0, 0);
            currNode.Tag = carpeta.id;
            currNode.Name = carpeta.name;


            if (carpeta.folders is List<Folder>)
                foreach (Folder subFolder in carpeta.folders)
                    currNode.Nodes.Add(CarpetaToNodo(subFolder));


            if (carpeta.files is List<Sound>)
            {
                foreach (Sound archivo in carpeta.files)
                {
                    int formato = FormatoToImage(archivo.type);
                    TreeNode fileNode = new TreeNode(archivo.name, formato, formato);
                    fileNode.Name = archivo.name;
                    fileNode.Tag = archivo.id;
                    currNode.Nodes.Add(fileNode);
                    if (archivo.type == FormatSound.SSAR)
                    {
                        BinaryReader ssa = new BinaryReader(new MemoryStream(file));
                        ssa.BaseStream.Position = archivo.offset;
                        ssar.SSAR_File sa = ssar.Read(ssa.ReadBytes((int)archivo.size));
                        ssa.Close();
                        int nr = 0;
                        foreach (ssar.SSAR_File.data.SSAR_Record s in sa.Data.Records)
                        {
                            TreeNode ssarNode;
                            if (sd.symbol.record2.nEntries != 0)
                            {
                                ssarNode = new TreeNode(sd.symbol.record2.group[fileNode.Index].subRecord.entries[nr], 3, 3);
                            }
                            else
                            {
                                ssarNode = new TreeNode("Sequence " + nr.ToString(), 3, 3);
                            }
                            ssarNode.Tag = new object[]{s, sa.Data.NoteData};
                            fileNode.Nodes.Add(ssarNode);
                            nr++;
                        }
                    }
                    else if (archivo.type == FormatSound.SWAR)
                    {
                        BinaryReader ssa = new BinaryReader(new MemoryStream(file));
                        ssa.BaseStream.Position = archivo.offset;
                        SDAT.SWAR.ArchivoSWAR sa = SDAT.SWAR.LeerArchivo(ssa.ReadBytes((int)archivo.size));
                        ssa.Close();
                        SDAT.SWAV.ArchivoSWAV[] swa = SDAT.SWAR.ConvertirASWAV(sa);
                        int nr = 0;
                        foreach (SDAT.SWAV.ArchivoSWAV s in swa)
                        {
                            TreeNode ssarNode;
                            //if (sd.symbol.record2.nEntries != 0)
                            //{
                            //    ssarNode = new TreeNode(sd.symbol.record2.group[fileNode.Index].subRecord.entries[nr], 3, 3);
                            //}
                            //else
                            //{
                                ssarNode = new TreeNode("Wave " + nr.ToString(), 3, 3);
                            //}
                            ssarNode.Tag = s;
                            fileNode.Nodes.Add(ssarNode);
                            nr++;
                        }
                    }
                }
            }

            return currNode;

        }
        private void sdat__Load(object sender, EventArgs e)
        {
            SDAT.SDAT s = new SDAT.SDAT();
            s.Leer(name, file);
            sd = s.Informacion();
            treeView1.Nodes.Add(CarpetaToNodo(sd.files.root));
        }
        void read()
        {
            EndianBinaryReader er = new EndianBinaryReader(File.OpenRead(name));

        }
        private int FormatoToImage(FormatSound formato)
        {
            switch (formato)
            {
                case FormatSound.SSEQ:
                    //return 2; No soportado este formato aún
                    return 3;
                case FormatSound.SSAR:
                    //return 2; No soportado este formato aún
                    return 5;
                case FormatSound.SBNK:
                    //return 4; No soportado este formato aún
                    return 4;
                case FormatSound.SWAV:
                    return 1;
                case FormatSound.SWAR:
                    return 2;
                case FormatSound.STRM:
                    //return 1; No soportado este formato aún
                    return 7;
                default:
                    return 6;
            }
        }
        private Sound SearchFile()
        {
            return SearchFile(Convert.ToInt32(treeView1.SelectedNode.Tag), sd.files.root);
        }
        private Sound SearchFile(int id, Folder carpeta)
        {
            if (carpeta.files is List<Sound>)
                foreach (Sound archivo in carpeta.files)
                    if (archivo.id == id)
                        return archivo;


            if (carpeta.folders is List<Folder>)
            {
                foreach (Folder subFolder in carpeta.folders)
                {
                    Sound currFile = SearchFile(id, subFolder);
                    if (currFile.name is String)
                        return currFile;
                }
            }


            return new Sound();
        }
        private Folder SearchFolder(int id, Folder carpeta)
        {
            if (carpeta.id == id)
                return carpeta;

            if (carpeta.folders is List<Folder>)
            {
                foreach (Folder subFolder in carpeta.folders)
                {
                    Folder currFolder = SearchFolder(id, subFolder);
                    if (currFolder.name is String)
                        return currFolder;
                }
            }


            return new Folder();
        }
        public byte[] sbnk;
        private void treeView1_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (e.Node.Tag is object[])
            {
                ssar.SSAR_File.data.SSAR_Record r = (ssar.SSAR_File.data.SSAR_Record)((e.Node.Tag as object[])[0]);
                byte[] data = (byte[])((e.Node.Tag as object[])[1]);
                SDAT.Sound SBNKFile = new Sound();
                SDAT.Info.BANK b = new Info.BANK();
                b = (SDAT.Info.BANK)sd.info.block[2].entries[r.bnk];
                SBNKFile = SearchFile(b.fileID, sd.files.root);// sd.files.root.folders[2].files[b.fileID - sd.files.root.folders[0].files.Count - sd.files.root.folders[1].files.Count];
                byte[] sseqq = data;
                if (SBNKFile.size != 0)
                {
                    try
                    {
                        BinaryReader ss2 = new BinaryReader(new MemoryStream(file));
                        ss2.BaseStream.Position = SBNKFile.offset;
                        ushort[] waves = b.wa;
                        sbnk = ss2.ReadBytes((int)SBNKFile.size);
                        sseq.Sbnk sbn = sseq.readSBNK(sbnk);
                        List<SWAR.ArchivoSWAR> sss = new List<SWAR.ArchivoSWAR>();
                        for (int i = 0; i < 4; i++)
                        {
                            if (waves[i] == 0xffff) { sss.Add(new SDAT.SWAR.ArchivoSWAR()); continue; }
                            ss2.BaseStream.Position = SearchFile(((SDAT.Info.WAVEARC)sd.info.block[3].entries[waves[i]]).fileID, sd.files.root).offset;// sd.files.root.folders[3].files[waves[i]].offset;
                            sss.Add(SWAR.LeerArchivo(ss2.ReadBytes((int)SearchFile(((SDAT.Info.WAVEARC)sd.info.block[3].entries[waves[i]]).fileID, sd.files.root).size)));
                        }

                        sbn = sseq.setWaves(sbn, sss.ToArray());
                        Form s3 = new sseq(sseqq, (int)r.Offset, sseq.writeDLS(sbn), m);
                        s3.ShowDialog();
                        if (File.Exists("C:\\tmp.dls"))
                        {
                            bool done;
                            do
                            {
                                try
                                {
                                    File.Delete("C:\\tmp.dls");
                                    done = true;
                                }
                                catch
                                {
                                    done = false;
                                }
                            }
                            while (!done);
                        }
                    }
                    catch (IndexOutOfRangeException ex)
                    {
                        Form s3 = new sseq(sseqq, (int)r.Offset, null, m);
                        s3.ShowDialog();
                    }

                }
                else
                {
                    Form s3 = new sseq(sseqq, (int)r.Offset, null, m);
                    s3.ShowDialog();
                }
                return;
            }
            else if (e.Node.Tag is SDAT.SWAV.ArchivoSWAV)
            {
                Form s = new swav(SDAT.SWAV.EscribirArchivo((SDAT.SWAV.ArchivoSWAV)(e.Node.Tag)), "Wave");
                s.ShowDialog();
                return;
            }
            int id = Convert.ToInt32(e.Node.Tag);
            if (id < 0x0F000)
            {
                Sound fileSelect = SearchFile(id, sd.files.root);

                switch (fileSelect.type)
                {
                    case FormatSound.SWAV:
                        BinaryReader br = new BinaryReader(new MemoryStream(file));
                        br.BaseStream.Position = fileSelect.offset;
                        Form s = new swav(br.ReadBytes((int)fileSelect.size), fileSelect.name);
                        br.Close();
                        s.ShowDialog();
                        break;
                   /* case FormatSound.SWAR:
                        BinaryReader br1 = new BinaryReader(new MemoryStream(file));
                        br1.BaseStream.Position = fileSelect.offset;
                        Form s1 = new swar(br1.ReadBytes((int)fileSelect.size), fileSelect.name);
                        br1.Close();
                        s1.ShowDialog();
                        break;*/
                    case FormatSound.STRM:
                        BinaryReader br2 = new BinaryReader(new MemoryStream(file));
                        br2.BaseStream.Position = fileSelect.offset;
                        Form s2 = new strm(br2.ReadBytes((int)fileSelect.size), fileSelect.name);
                        br2.Close();
                        s2.ShowDialog();
                        break;
                    case FormatSound.SSEQ:
                        {
                            BinaryReader ss = new BinaryReader(new MemoryStream(file));
                            ss.BaseStream.Position = fileSelect.offset;
                            SDAT.Sound SBNKFile = new Sound();
                            SDAT.Info.BANK b = new Info.BANK();
                            foreach (SDAT.Info.SEQ stt in sd.info.block[0].entries)
                            {
                                if (stt.fileID == fileSelect.internalID)
                                {
                                    b = (SDAT.Info.BANK)sd.info.block[2].entries[stt.bnk];
                                    SBNKFile = sd.files.root.folders[2].files[b.fileID - sd.files.root.folders[0].files.Count - sd.files.root.folders[1].files.Count];
                                    break;
                                }
                            }
                            byte[] sseqq = ss.ReadBytes((int)fileSelect.size);
                            ss.Close();
                            if (SBNKFile.size != 0)
                            {
                                try
                                {
                                    BinaryReader ss2 = new BinaryReader(new MemoryStream(file));
                                    ss2.BaseStream.Position = SBNKFile.offset;
                                    ushort[] waves = b.wa;
                                    sbnk = ss2.ReadBytes((int)SBNKFile.size);
                                    sseq.Sbnk sbn = sseq.readSBNK(sbnk);
                                    List<SWAR.ArchivoSWAR> sss = new List<SWAR.ArchivoSWAR>();
                                    for (int i = 0; i < 4; i++)
                                    {
                                        if (waves[i] == 0xffff) { sss.Add(new SDAT.SWAR.ArchivoSWAR()); continue; }
                                        ss2.BaseStream.Position = SearchFile(((SDAT.Info.WAVEARC)sd.info.block[3].entries[waves[i]]).fileID, sd.files.root).offset;// sd.files.root.folders[3].files[waves[i]].offset;
                                        sss.Add(SWAR.LeerArchivo(ss2.ReadBytes((int)SearchFile(((SDAT.Info.WAVEARC)sd.info.block[3].entries[waves[i]]).fileID, sd.files.root).size)));
                                    }

                                    sbn = sseq.setWaves(sbn, sss.ToArray());
                                        /*try
                                        {
                                            m.SetDLS(null);
                                            m.SetMidi("");
                                            m.Play();
                                            m.Stop();
                                        }
                                        catch
                                        {
                                            m.Unload();
                                        }  */
                                        Form s3 = new sseq(sseqq, fileSelect.name, sseq.writeDLS(sbn), m);
                                        s3.ShowDialog();
                                        //t.Abort();
                                        //t = null;
                                        //while (!end) ;
                                        //t.Abort();
                                    
                                }
                                catch (IndexOutOfRangeException ex)
                                {
                                    Form s3 = new sseq(sseqq, fileSelect.name, null, m);
                                    s3.ShowDialog();
                                }

                            }
                            else
                            {
                                Form s3 = new sseq(sseqq, fileSelect.name, null, m);
                                s3.ShowDialog();
                            }

                        }
                        break;
                    case FormatSound.SBNK:
                        {
                            BinaryReader ss2 = new BinaryReader(new MemoryStream(file));
                            ss2.BaseStream.Position = fileSelect.offset;
                            ushort[] waves = new ushort[4];
                            foreach (SDAT.Info.BANK stt in sd.info.block[2].entries)
                            {
                                if (stt.fileID == fileSelect.id)
                                {
                                    waves = stt.wa;
                                    break;
                                }
                            }
                            sbnk = ss2.ReadBytes((int)fileSelect.size);
                            sseq.Sbnk sbn = sseq.readSBNK(sbnk);
                            List<SWAR.ArchivoSWAR> sss = new List<SWAR.ArchivoSWAR>();
                            for (int i = 0; i < 4; i++)
                            {
                                if (waves[i] == 0xffff) { sss.Add(new SDAT.SWAR.ArchivoSWAR()); continue; }
                                ss2.BaseStream.Position = SearchFile(((SDAT.Info.WAVEARC)sd.info.block[3].entries[waves[i]]).fileID, sd.files.root).offset;// sd.files.root.folders[3].files[waves[i]].offset;
                                sss.Add(SWAR.LeerArchivo(ss2.ReadBytes((int)SearchFile(((SDAT.Info.WAVEARC)sd.info.block[3].entries[waves[i]]).fileID, sd.files.root).size)));
                            }
                            sbn = sseq.setWaves(sbn, sss.ToArray());
                            MKDS_Course_Editor.sbnk.DLS d = new MKDS_Course_Editor.sbnk.DLS(sbn);
                            d.ShowDialog();
                            //sseq.writeDLS(@"C:\test.dls", sbn);
                            ss2.Close();
                        }
                        break;
                }
            }
            else
            {
                Folder folSelect = SearchFolder(id, sd.files.root);
            }
        }
    }
}
